"""
CBJ聊天室
"""
import sys
import threading
from concurrent.futures import ThreadPoolExecutor
from functools import total_ordering
import re
import myConfig

import myUdpApi


@total_ordering
class Peer:
    """
    一个朋友
    """
    id: int
    name: str
    ip: str

    def __eq__(self, other):
        return self.id == other.id

    def __le__(self, other):
        return self.id <= other.id

    def __gt__(self, other):
        return self.id > other.id


class Node:
    """
    节点
    """

    ID = 0
    myName = str
    peers = {}
    net: str  # 192.168.180.1/24
    ip: str  # 192.168.180.1
    runFlag: bool

    def __init__(self, net: str, myName: str):
        self.myName = myName
        self.net = net
        self.ip = net.split('/')[0]
        self.udp = myUdpApi.MyUDPSocket(self.net)
        self.threadPool = ThreadPoolExecutor(max_workers=3)
        self.runFlag = True

    def start(self):
        """
        启动聊天室
        """
        # 广播自己的信息
        self.introduceMyself()
        # 接收广播
        self.threadPool.submit(self.recvBroadcast)
        # 发送消息
        self.threadPool.submit(self.send)
        # 接收消息
        self.threadPool.submit(self.recv)

    def exit(self):
        """
        优雅地退出
        """
        self.runFlag = False
        self.udp.close()
        print('exit OK')
        exit()

    def introduceMyself(self):
        """
        广播自己的信息
        """
        threading.Thread(target=self.udp.sendBroadcast, args=(myConfig.sbMessage + self.myName,)).start()

    def send(self):
        """
        发送UDP消息
        """
        while self.runFlag:
            text = input("$")
            if text == "quit":
                print('start to quit')
                self.exit()
            else:
                for peer in self.peers:
                    self.udp.send_json((peer, myConfig.commonPort), {'type': 'msg', 'data': text})

    def recv(self):
        """
        接收UDP消息
        """
        while self.runFlag:
            dic, addr = self.udp.recv_json()
            # print(dic, addr)
            print(f"\n{self.peers[addr[0]]}: {dic['data']}\n$", end='')

    def recvBroadcast(self):
        """
        接收广播消息
        """
        while self.runFlag:
            # API中有标志变量可以退出, 所以这里不用循环等待
            # print('start recv')
            ret = self.udp.recvBroadcast()
            if ret is not None:
                text, addr = ret
                ip, _ = addr
                # print(text)
                match = re.match(f"{myConfig.sbMessage}" + r"(.*)", text)
                if match is not None and ip != self.ip and ip not in self.peers.keys():
                    peerName = match.group(1)
                    self.peers[addr[0]] = peerName
                    print(text)
                    print(f"{peerName} from {addr} come in")
                    print(self.peers)
                    self.introduceMyself()


if __name__ == '__main__':
    try:
        myNet = sys.argv[1]
        name = sys.argv[2]
    except IndexError as e:
        myNet = "192.168.180.1/24"
        name = "CBJ"
        print('default setting')
    node = Node(myNet, name)
    node.start()
